﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
using Microsoft.TeamFoundation.VersionControl.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Build.Proxy;
using System.IO;
using TFSServices.Common;
using Microsoft.TeamFoundation;

namespace Shaw.TfsTool.WcfTfsService
{
    public class TfsService : ITfsService
    {
         /// <summary>
        /// Retrieves a list of Team projects with bug work items in resolved or active state
        /// </summary>
        /// <param name="tfsServerName">A <see cref="String"/> containing the server name or the full TFS Server url</param>
        /// <returns>a <see cref="TeamProjects"/> collection</returns>
        public TeamProjects GetProjectStatus(
            String tfsServerName,
            String workItemTypeName)
        {
            TeamProjects teamProjects = new TeamProjects();

            try
            {
                // Connect to the chosen TFS server
                TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(
                    tfsServerName);

                tfs.Authenticate();

                // Connect to the WorkItem Store
                WorkItemStore store = (WorkItemStore)tfs.GetService(typeof(WorkItemStore));

                foreach (Project project in store.Projects)
                {
                    String query = String.Format(
                        "Select [System.State] from WorkItems where " +
                        "[System.TeamProject] = '{0}' AND [System.WorkItemType] = '{1}'",
                        project.Name, workItemTypeName);

                    WorkItemCollection workitems = store.Query(query);
                    Int32 activeItems = 0;
                    Int32 resolvedItems = 0;
                    Int32 closedItems = 0;

                    if (workitems.Count > 0)
                    {
                        foreach (WorkItem workitem in workitems)
                        {
                            switch (workitem.State)
                            {
                                case "Active":
                                    activeItems++;
                                    break;
                                case "Resolved":
                                    resolvedItems++;
                                    break;
                                case "Closed":
                                    closedItems++;
                                    break;
                            }
                        }

                        // Add team project to result list only if it has active bugs
                        if (activeItems > 0 || resolvedItems > 0)
                        {
                            teamProjects.Add(new TFSServices.Common.TeamProject()
                            {
                                Name = project.Name,
                                ActiveItems = activeItems,
                                ResolvedItems = resolvedItems,
                                ClosedItems = closedItems,
                            });
                        }
                    }
                }
            }
            catch (TeamFoundationInvalidServerNameException ex)
            {
                //TODO: Implement Invalid ServerName exception handling
                throw;
            }
            catch (TeamFoundationServerUnauthorizedException ex)
            {
                //TODO: Implement Unauthorized Exception handling
                throw;
            }
            catch (Exception ex)
            {
                //TODO: Implement exception handling
                throw;
            }

            return teamProjects;
        }

        /// <summary>
        /// Retrieves a list of Team projects with active Build Types
        /// </summary>
        /// <param name="tfsServerName">A <see cref="String"/> containing the server name or the full TFS Server url</param>
        /// <returns>a <see cref="TeamProjects"/> collection</returns>
        public TeamProjects GetBuildStatus(String tfsServerName)
        {
            TeamProjects teamProjects = new TeamProjects();

            try
            {
                // Connect to the chosen TFS server
                TeamFoundationServer tfs = TeamFoundationServerFactory.GetServer(
                    tfsServerName);

                tfs.Authenticate();


                ICommonStructureService commonService = (ICommonStructureService)tfs.GetService(
                    typeof(ICommonStructureService));

                VersionControlServer versionControlServer = (VersionControlServer)tfs.GetService(
                    typeof(VersionControlServer));

                BuildStore bs = (BuildStore)tfs.GetService(
                    typeof(BuildStore));

                // Get a list of projects
                ProjectInfo[] tfsProjects = commonService.ListProjects();

                foreach (ProjectInfo teamProject in tfsProjects)
                {
                    // Add team project to result list
                    teamProjects.Add(new TFSServices.Common.TeamProject()
                    {
                        Name = teamProject.Name,
                    });

                    // get the Build Types
                    ItemSet itemSet = versionControlServer.GetItems(
                        "$/" + teamProject.Name + "/TeamBuildTypes/",
                        VersionSpec.Latest,
                        RecursionType.OneLevel,
                        DeletedState.NonDeleted,
                        ItemType.Folder);

                    // Check if there are one or more BuildTypes defined 
                    // for the active Team project
                    if (itemSet.Items.Count() > 0)
                    {
                        foreach (Item item in itemSet.Items)
                        {
                            // Check if the Item is not a folder
                            if (!Path.GetFileName(item.ServerItem).Equals("TeamBuildTypes"))
                            {
                                BuildType bType = null;

                                // Retrieve the BuilType from the BuildTypes list if exist
                                // for update purposes
                                bType = teamProjects[teamProjects.Count() - 1].BuildTypes.Find(
                                   delegate(BuildType buildType)
                                   {
                                       return (buildType.Name == Path.GetFileName(item.ServerItem));
                                   });

                                // Check if the Build Type has been added to the list of TeamProjects 
                                if (bType == null)
                                {
                                    bType = new BuildType()
                                    {
                                        Name = Path.GetFileName(item.ServerItem),
                                        Status = "N/A",
                                        NumberOfConsecutiveBuilds = 0
                                    };

                                    teamProjects[teamProjects.Count() - 1].BuildTypes.Add(bType);
                                }

                                // Get the builds
                                BuildData[] buildData = bs.GetListOfBuilds(teamProject.Name, bType.Name);

                                String lastBuildStatus = String.Empty;

                                foreach (BuildData data in buildData)
                                {
                                    if (data.BuildStatus != lastBuildStatus)
                                    {
                                        bType.NumberOfConsecutiveBuilds = 0;
                                        lastBuildStatus = data.BuildStatus;
                                    }

                                    bType.Status = data.BuildStatus;
                                    bType.NumberOfConsecutiveBuilds++;
                                    bType.LastBuild = data.FinishTime.Year == 1 ? data.StartTime : data.FinishTime;
                                }
                            }
                        }
                    }

                }
            }
            catch (TeamFoundationInvalidServerNameException ex)
            {
                //TODO: Implement Invalid ServerName exception handling
                throw;
            }
            catch (TeamFoundationServerUnauthorizedException ex)
            {
                //TODO: Implement Unauthorized Exception handling
                throw;
            }
            catch (Exception ex)
            {
                //TODO: Implement exception handling
                throw;
            }

            return teamProjects;
        }
    }
}
